這應該也是很多人剛開始接觸Flutter時心裡會有的疑問,而對於當年逃離Java的魔掌,和Kotlin墜入愛河,度過兩年纏綿悱惻如膠似漆的生活的我來說,看到Dart這個捉襟肘見衣衫襤褸的語言,心中也不免浮起了對它的鄙視和不屑。明明Kotlin都已經成為Android的官方語言了,到底為什麼Google不直接拿它來開發Flutter呢?
這樣的想法在熟悉Dart並實際進入開發階段後,很快就完全消失了。雖然直到今天我還是經常抱怨為什麼Dart沒有Kotlin的某某語法,但如果要讓我來選擇Flutter的開發語言,我也百分之百會和Flutter團隊做出一樣的選擇,擁抱Dart這個當年爹不疼娘不愛的孩子。
那麼,到底是什麼讓Dart脫穎而出,成為無數程式語言中,Flutter團隊的首選?
首先,最最重要的一點就是Dart多樣化的編譯方式。一般來說,靜態型別語言(ex.C/C++)主要是以AOT(Ahead Of Time)的方式編譯,而動態型別語言(ex.Javascript)則是以JIT(Just In Time的方式編譯。而Dart作為一個靜態型別語言,不但眾多程式語言中少數同時支援AOT和JIT的語言,更可以轉譯成Javascript,甚至還可以作為直譯式語言,直接在Dart VM上執行。支援JIT編譯讓Flutter在開發階段能夠透過Hot Reload進行極為快速的迭代,而支援AOT編譯則讓Flutter能在佈署時產生啟動快、執行快且可預期的ARM Code。透過Dart實現的Stateful Hot Reload不只是大幅提昇了Flutter的開發效率,也進一步影響了Flutter UI的編寫方式,讓我們繼續看下去。
在早期的原生開發中,不論是Android或iOS,編寫UI時大多都會使用各自的樣版語言(XML/xib),並搭配IDE提供的工具進行快速編輯和預覽。當然也有人因為各種因素選擇直接使用程式碼來編寫UI,但相對的就必須經過冗長的編譯過程才能看到改動的結果。Stateful Hot Reload徹底解決了這個問題。當我們可以在毫秒內在裝置上直接看到我們改動UI程式碼的結果,我們就不再需要IDE的輔助工具來進行預覽,同時也就不需要另一套輔助的樣版語言來編寫UI。當我們可以使用一套語言,在一個領域完成所有UI相關的程式碼,不但讓Flutter的學習門檻進一步下降,也避免了在不同程式語言和樣版語言間進行情境轉換所造成的開發效率損失。最後,當你使用程式語言而非樣版語言來撰寫UI,你的UI程式碼同時也得到了該語言的所有特性、彈性和安全性。你也不再須要奇特的語法來將一點點程式塞入樣板中(ex. Android Databinding, React JSX),你可以擁有全部。
再次強調,沒有Hot Reload這一切都不會發生,而Dart是世上少數同時擁有JIT和AOT的語言,在實現了Hot Reload的同時也能兼顧到發佈時的效能。
首先,Flutter UI設計受到了React很大的啟發,它是陳述式以及複合式的。不同於React的是,Dart作為物件導向語言,自然是以Class而非Function作為複合的主要元素。最後,Flutter不但採取了複合,而且還進一步實作成了激進式複合。套一個簡單的背景色,你得複合一個DecoratedBox。想讓元件置中,你要再複合一個Center。想加入點擊事件,再一個GestureDectector。記得,這每一層都是一個須要被分配的物件。這樣的設計讓Flutter在繪製UI時必須不斷分配和回收大量微小又短命的物件,而Dart獨特的物件分配和回收機制正好適合這個任務,使其不會在GC時卡住Flutter引以為傲的60FPS。
Dart有沒有缺點呢?當然有。當年的Dart可以說是極為小眾,被戲稱為是Google的自嗨語言,特性也不如C#, Swift, Kotlin等那麼強大豐富。然而對很多開發者來說是致命傷的缺點,對Flutter團隊來說卻是一大優點。由Google開發且小眾,使得Flutter團隊可以極大程度的影響Dart的未來發展。例如前面被我大吹特吹的JIT和AOT編譯,其實一開始Dart也只有JIT,而AOT正是Dart團隊為了Flutter才特別開發的!來自Android/iOS/Web的各路人馬也在開發Flutter的過程中,感受到了Dart的不足之處,進而為Dart帶來許多在其它語言中,經過長久驗證的優質特性(ex. extension, NNBD)。除此之外,Dart團隊自身也持續在改進,增加了不少特別適合Flutter的語法(ex. collection-if, collection-for)。
總結來說,未來Dart在語法特性上很可能會逐漸趕上C#, Swift, Kotlin等其它強大的語言,但同時又保有最重要的多編譯模式。試想如果當初Flutter團隊選擇的是Kotlin,能有多少影響力請Kotlin團隊放下所有issue/feature,全力開發能支援極快速Stateful Hot Reload的JIT/AOT雙編譯模式?我想可以說Flutter團隊不是選擇了Dart,而是選擇了一個能讓它盡情使喚栽培的,年輕但潛力無窮的程式語言。